__metaclass__ = type

from noop import noop, reset

class group:

    def __init__(self, comps=None, func=noop, pre=reset, post=noop):
        if comps is None:
            comps = []
        self._data = comps
        self.func = func
        self.pre = pre
        self.post = post
        self.children = []
        self.code = []

    def __getattribute__(self, attr):
        if attr in ['__call__', '__len__', '_data',
                    'func', 'children', '__iter__',
                    'pre', 'post', 'code']:
            return object.__getattribute__(self, attr)
        return object.__getattribute__(self._data, attr)

    def __iter__(self):
        return iter(self._data)

    def __len__(self):
        return max(map(len, self._data))

    def __call__(self, target):
        self.pre(target, self)
        for c in self:
            target = list(target)
            c.pre(target, c)
            r = c(target)
            if r:
                eat = len(target)
                if r is not True:
                    eat = len(target) - len(r)
                tokens = target[:eat]
                children = c.func(tokens, c)
                self.children.extend(children)
                c.post(tokens, c)
                self.post(target, self)
                self.code.extend(c.code)
                return r
        return False

    def __repr__(self):
        items = map(str, self._data)
        return '[%s]' % '|'.join(items)

